package com.reactim.message.connection;

import com.github.benmanes.caffeine.cache.Cache;
import com.reactim.message.config.CacheConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.messaging.rsocket.RSocketRequester;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 带缓存的连接管理器
 * 在委托连接管理器基础上添加本地缓存功能
 */
@Component
@Slf4j
public class CachedConnectionManager implements ConnectionManager {
    
    private final ConnectionManager delegateManager;
    private final Cache<Long, ConnectionDetails> connectionDetailsCache;
    private final Cache<Long, Boolean> onlineStatusCache;
    private final Cache<String, Long> statsCache;
    private final CacheConfig cacheConfig;

    public CachedConnectionManager(
            @Qualifier("distributedConnectionManager") ConnectionManager delegateManager,
            @Qualifier("connectionDetailsCache") Cache<Long, ConnectionDetails> connectionDetailsCache,
            @Qualifier("onlineStatusCache") Cache<Long, Boolean> onlineStatusCache,
            @Qualifier("statsCache") Cache<String, Long> statsCache,
            CacheConfig cacheConfig) {
        this.delegateManager = delegateManager;
        this.connectionDetailsCache = connectionDetailsCache;
        this.onlineStatusCache = onlineStatusCache;
        this.statsCache = statsCache;
        this.cacheConfig = cacheConfig;
    }
    
    @Override
    public Mono<Boolean> storeConnection(Long userId, RSocketRequester requester, ConnectionInfo connectionInfo) {
        return delegateManager.storeConnection(userId, requester, connectionInfo)
                .doOnSuccess(success -> {
                    if (success) {
                        // 清除相关缓存
                        connectionDetailsCache.invalidate(userId);
                        onlineStatusCache.put(userId, true);
                        log.debug("连接存储成功，更新缓存: userId={}", userId);
                    }
                });
    }
    
    @Override
    public Mono<ConnectionDetails> getConnection(Long userId) {
        // 先检查缓存
        ConnectionDetails cached = connectionDetailsCache.getIfPresent(userId);
        if (cached != null) {
            log.debug("从缓存获取连接信息: userId={}", userId);
            return Mono.just(cached);
        }
        
        // 缓存未命中，从委托管理器获取
        return delegateManager.getConnection(userId)
                .doOnNext(details -> {
                    // 更新缓存
                    connectionDetailsCache.put(userId, details);
                    log.debug("连接信息已缓存: userId={}", userId);
                });
    }
    
    @Override
    public Mono<Boolean> removeConnection(Long userId) {
        return delegateManager.removeConnection(userId)
                .doOnSuccess(success -> {
                    if (success) {
                        // 清除相关缓存
                        connectionDetailsCache.invalidate(userId);
                        onlineStatusCache.invalidate(userId);
                        log.debug("连接移除成功，清除缓存: userId={}", userId);
                    }
                });
    }
    
    @Override
    public Mono<Boolean> isUserOnline(Long userId) {
        // 先检查缓存
        Boolean cached = onlineStatusCache.getIfPresent(userId);
        if (cached != null) {
            log.debug("从缓存获取在线状态: userId={}, online={}", userId, cached);
            return Mono.just(cached);
        }
        
        // 缓存未命中，从委托管理器获取
        return delegateManager.isUserOnline(userId)
                .doOnNext(online -> {
                    // 更新缓存
                    onlineStatusCache.put(userId, online);
                    log.debug("在线状态已缓存: userId={}, online={}", userId, online);
                });
    }
    
    @Override
    public Mono<Long> getOnlineUserCount() {
        // 检查统计缓存
        String cacheKey = "online_user_count";
        Long cached = statsCache.getIfPresent(cacheKey);
        if (cached != null) {
            log.debug("从缓存获取在线用户数: {}", cached);
            return Mono.just(cached);
        }
        
        // 缓存未命中，从委托管理器获取
        return delegateManager.getOnlineUserCount()
                .doOnNext(count -> {
                    // 更新缓存
                    statsCache.put(cacheKey, count);
                    log.debug("在线用户数已缓存: {}", count);
                });
    }
    
    @Override
    public Mono<Void> sendMessageToUser(Long userId, String route, Object message) {
        return delegateManager.sendMessageToUser(userId, route, message);
    }
    
    @Override
    public Mono<Boolean> updateLastActiveTime(Long userId) {
        return delegateManager.updateLastActiveTime(userId)
                .doOnSuccess(success -> {
                    if (success) {
                        // 清除连接详情缓存，因为最后活跃时间已更新
                        connectionDetailsCache.invalidate(userId);
                        log.debug("最后活跃时间更新，清除连接详情缓存: userId={}", userId);
                    }
                });
    }
    
    /**
     * 批量获取在线状态
     */
    public Mono<Map<Long, Boolean>> batchGetOnlineStatus(List<Long> userIds) {
        Map<Long, Boolean> result = new HashMap<>();
        List<Long> uncachedUserIds = new java.util.ArrayList<>();
        
        // 先从缓存获取
        for (Long userId : userIds) {
            Boolean cached = onlineStatusCache.getIfPresent(userId);
            if (cached != null) {
                result.put(userId, cached);
            } else {
                uncachedUserIds.add(userId);
            }
        }
        
        // 如果所有数据都在缓存中
        if (uncachedUserIds.isEmpty()) {
            return Mono.just(result);
        }
        
        // 批量获取未缓存的数据
        return Mono.fromCallable(() -> {
            for (Long userId : uncachedUserIds) {
                Boolean online = delegateManager.isUserOnline(userId).block();
                result.put(userId, online);
                onlineStatusCache.put(userId, online);
            }
            return result;
        });
    }
    
    /**
     * 批量获取连接详情
     */
    public Mono<Map<Long, ConnectionDetails>> batchGetConnections(List<Long> userIds) {
        Map<Long, ConnectionDetails> result = new HashMap<>();
        List<Long> uncachedUserIds = new java.util.ArrayList<>();
        
        // 先从缓存获取
        for (Long userId : userIds) {
            ConnectionDetails cached = connectionDetailsCache.getIfPresent(userId);
            if (cached != null) {
                result.put(userId, cached);
            } else {
                uncachedUserIds.add(userId);
            }
        }
        
        // 如果所有数据都在缓存中
        if (uncachedUserIds.isEmpty()) {
            return Mono.just(result);
        }
        
        // 批量获取未缓存的数据
        return Mono.fromCallable(() -> {
            for (Long userId : uncachedUserIds) {
                ConnectionDetails details = delegateManager.getConnection(userId).block();
                if (details != null) {
                    result.put(userId, details);
                    connectionDetailsCache.put(userId, details);
                }
            }
            return result;
        });
    }
    
    /**
     * 批量更新最后活跃时间
     */
    public Mono<Map<Long, Boolean>> batchUpdateLastActiveTime(List<Long> userIds) {
        return Mono.fromCallable(() -> {
            Map<Long, Boolean> result = new HashMap<>();
            for (Long userId : userIds) {
                Boolean success = delegateManager.updateLastActiveTime(userId).block();
                result.put(userId, success);
                if (success) {
                    // 清除连接详情缓存
                    connectionDetailsCache.invalidate(userId);
                }
            }
            return result;
        });
    }
    
    /**
     * 获取缓存统计信息
     */
    public Map<String, Object> getCacheStats() {
        Map<String, Object> stats = new HashMap<>();
        
        // 连接详情缓存统计
        Map<String, Object> connectionStats = new HashMap<>();
        connectionStats.put("size", connectionDetailsCache.estimatedSize());
        connectionStats.put("stats", connectionDetailsCache.stats());
        stats.put("connectionDetailsCache", connectionStats);
        
        // 在线状态缓存统计
        Map<String, Object> onlineStats = new HashMap<>();
        onlineStats.put("size", onlineStatusCache.estimatedSize());
        onlineStats.put("stats", onlineStatusCache.stats());
        stats.put("onlineStatusCache", onlineStats);
        
        // 统计缓存统计
        Map<String, Object> statsStats = new HashMap<>();
        statsStats.put("size", statsCache.estimatedSize());
        statsStats.put("stats", statsCache.stats());
        stats.put("statsCache", statsStats);
        
        return stats;
    }
    
    /**
     * 清理过期缓存
     */
    public void cleanupExpiredCache() {
        connectionDetailsCache.cleanUp();
        onlineStatusCache.cleanUp();
        statsCache.cleanUp();
        log.debug("缓存清理完成");
    }
    
    /**
     * 清理所有缓存
     */
    public void clearAllCaches() {
        connectionDetailsCache.invalidateAll();
        onlineStatusCache.invalidateAll();
        statsCache.invalidateAll();
        log.info("所有缓存已清理");
    }
    
    /**
     * 刷新缓存
     */
    public void refreshCache() {
        // 清理过期缓存
        cleanupExpiredCache();
        log.info("缓存已刷新");
    }
    
    @Override
    public Mono<List<ConnectionDetails>> getConnectionsByInstance(String instanceId) {
        return delegateManager.getConnectionsByInstance(instanceId);
    }
}